#include <QLabel>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostInfo>
#include <QPushButton>
#include "mainwindow_tcp_server.h"
#include "ui_mainwindow_tcp_server.h"

MainWindow_tcp_server::MainWindow_tcp_server(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow_tcp_server)
    , tcp_server_(new QTcpServer(this))
    , tcp_socket_(nullptr)
{
    ui->setupUi(this);

    init_widgets();
    init_connections();

    setAttribute(Qt::WA_DeleteOnClose);
}

MainWindow_tcp_server::~MainWindow_tcp_server()
{
    delete ui;

    del_pointer(tcp_socket_);
    del_pointer(tcp_server_);
    del_pointer(lbl_socket_state_);
    del_pointer(lbl_listen_);
}

void MainWindow_tcp_server::closeEvent(QCloseEvent *event)
{
    if (tcp_server_->isListening()) {
        tcp_server_->close();
    }

    event->accept();
}

QString MainWindow_tcp_server::get_local_ip() const
{
    // 获取主机信息
    QHostInfo host_info = QHostInfo::fromName(QHostInfo::localHostName());

    QList<QHostAddress> add_list = host_info.addresses();

    QString local_ip = "";
    if ( !add_list.isEmpty()) {
        for (int i(0); add_list.count() != i; ++i) {
            QHostAddress host = add_list.at(i);

            if (QAbstractSocket::IPv4Protocol == host.protocol()) {
                local_ip = host.toString();
                break;
            }
        }
    }

    return local_ip;
}

void MainWindow_tcp_server::init_widgets()
{
    ui->action_stop_listen_->setEnabled(false);

    lbl_listen_ = new QLabel(tr("监听状态"), this);
    lbl_listen_->setMinimumWidth(150);
    ui->statusbar->addWidget(lbl_listen_);

    lbl_socket_state_ = new QLabel(tr("Socket状态"), this);
    lbl_socket_state_->setMinimumWidth(200);
    ui->statusbar->addWidget(lbl_socket_state_);

    QString local_ip = get_local_ip();
    this->setWindowTitle(this->windowTitle() + "---本机IP" + local_ip);
    ui->combo_ip_->addItem(local_ip);
}

void MainWindow_tcp_server::init_connections()
{
    // newConnection signal is emitted every time a new connection is available.
    connect(tcp_server_, &QTcpServer::newConnection,
            this, &MainWindow_tcp_server::sl_init_socket_connections);

    connect(ui->action_start_listen_, &QAction::triggered,
            this, &MainWindow_tcp_server::sl_server_start_listen);

    connect(ui->action_stop_listen_, &QAction::triggered,
            this, &MainWindow_tcp_server::sl_server_stop_listen);

    connect(ui->action_clear_text_, &QAction::triggered,
            this, &MainWindow_tcp_server::sl_server_clear_plain_text);

    connect(ui->action_exit_, &QAction::triggered,
            this, &MainWindow_tcp_server::sl_exit_application);

    connect(ui->btn_send_message_, &QPushButton::clicked,
            this, &MainWindow_tcp_server::sl_button_send_message);
}

void MainWindow_tcp_server::sl_socket_state_change(QAbstractSocket::SocketState socket_state)
{
    switch ( socket_state) {
    case QAbstractSocket::UnconnectedState:
        lbl_socket_state_->setText("scoket状态：UnconnectedState");
        break;

    case QAbstractSocket::HostLookupState:
        lbl_socket_state_->setText("scoket状态：HostLookupState");
        break;

    case QAbstractSocket::ConnectingState:
        lbl_socket_state_->setText("scoket状态：ConnectingState");
        break;

    case QAbstractSocket::ConnectedState:
        lbl_socket_state_->setText("scoket状态：ConnectedState");
        break;

    case QAbstractSocket::BoundState:
        lbl_socket_state_->setText("scoket状态：BoundState");
        break;

    case QAbstractSocket::ClosingState:
        lbl_socket_state_->setText("scoket状态：ClosingState");
        break;

    default:
        lbl_socket_state_->setText("scoket状态：ListeningState");
        break;
    }
}

void MainWindow_tcp_server::sl_client_connected()
{
    ui->plainTextEdit->appendPlainText("**client socket connected");
    ui->plainTextEdit->appendPlainText("**peer address: " +
                                       tcp_socket_->peerAddress().toString());
    ui->plainTextEdit->appendPlainText("**peer port: " +
                                       QString::number(tcp_socket_->peerPort()));
}

void MainWindow_tcp_server::sl_client_disconnected()
{
    ui->plainTextEdit->appendPlainText("**client socket disconnected");

    // socket断开，释放资源
    tcp_socket_->deleteLater();
}

void MainWindow_tcp_server::sl_ready_read_from_socket()
{
    while ( tcp_socket_->canReadLine()) {
        ui->plainTextEdit->appendPlainText("[in] " + tcp_socket_->readLine());
    }
}

void MainWindow_tcp_server::sl_init_socket_connections()
{
    // 在服务器端获取已连接上的QTcpSocket
    tcp_socket_ = tcp_server_->nextPendingConnection();

    // 创立链接
    connect(tcp_socket_, &QTcpSocket::connected,
            this, &MainWindow_tcp_server::sl_client_connected);

    // 断开链接
    connect(tcp_socket_, &QTcpSocket::disconnected,
            this, &MainWindow_tcp_server::sl_client_disconnected);

    // 状态改变
    connect(tcp_socket_, &QTcpSocket::stateChanged,
            this, &MainWindow_tcp_server::sl_socket_state_change);

    // 读取数据
    connect(tcp_socket_, &QTcpSocket::readyRead,
            this, &MainWindow_tcp_server::sl_ready_read_from_socket);
}

void MainWindow_tcp_server::sl_server_start_listen()
{
    // 获取ip、端口
    QString ip = ui->combo_ip_->currentText().trimmed();
    quint16 port = static_cast<quint16>(ui->spin_port_->value());
    QHostAddress address(ip);

    // 设置服务器端监听的ip，端口
    tcp_server_->listen(address, port);

    // 设置窗体控件
    ui->plainTextEdit->appendPlainText("**开始监听...");
    ui->plainTextEdit->appendPlainText("***服务器地址：" +
                                       tcp_server_->serverAddress().toString());
    ui->plainTextEdit->appendPlainText("***服务器端口：" +
                                       QString::number(tcp_server_->serverPort()));
    ui->action_start_listen_->setEnabled(false);
    ui->action_stop_listen_->setEnabled(true);
    lbl_listen_->setText(tr("监听状态：正在监听"));
}

void MainWindow_tcp_server::sl_server_stop_listen()
{
    if ( tcp_server_->isListening()) {
        tcp_server_->close();
        ui->action_stop_listen_->setEnabled(false);
        ui->action_start_listen_->setEnabled(true);
        lbl_listen_->setText(tr("监听状态：已停止监听"));
        ui->plainTextEdit->appendPlainText("***停止监听...");
    }
}

void MainWindow_tcp_server::sl_server_clear_plain_text()
{
    ui->plainTextEdit->clear();
}

void MainWindow_tcp_server::sl_exit_application()
{
    qApp->closeAllWindows();
}

void MainWindow_tcp_server::sl_button_send_message()
{
    QString message = ui->edit_message_->text().trimmed();
    ui->plainTextEdit->appendPlainText(tr("[out] ") + message);
    ui->plainTextEdit->clear();
    ui->plainTextEdit->setFocus();

    // 将字符串转换为QByteArray类型
    QByteArray content = message.toUtf8();
    content.append('\n');

    // 将数据发送到客户端
    if ( tcp_socket_) {
        tcp_socket_->write(content);
    }
}

void MainWindow_tcp_server::del_pointer(QObject *obj)
{
    if (nullptr != obj) {
        delete obj;
        obj = nullptr;
    }
}
